<?php

/**
 * 权限类
 */
class Auth {

    protected static $_instance = null;
    public $options = array('salt' => '9lnk0s');
    public $id = 0;
    public $role_id = 0;
    public $fields = array();
    public $rolefields = array();
    public $permission = array();

    public function __get($name) {
        if (Yaf_Registry::has($name)) {
            return Yaf_Registry::get($name);
        }
    }

    public function __construct() {
        $this->load->library("cookie");
        $this->load->library("Yaf_Session", "session");
    }

    public static function getInstance() {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * 读取账户信息
     * @param int $id
     * @return array
     */
    public function get($id) {
        $one = $this->db->one("SELECT * FROM {pre}admin WHERE id = ?", array($id));
        return $one ? $one : array();
    }

    /**
     * 是否登录
     * @return boolean
     */
    public function is_login() {
        $id = $this->id ? $this->id : $this->cookie->get('id');
        if ($id) {
            if (isset($this->fields['id'])) {
                return TRUE;
            } else {
                $sessionid = $this->cookie->get("sessionid");
                $safecode = $this->cookie->get("safecode");
                if ($sessionid) {
                    $row = $this->get($id);
                    if ($row && $row['sessionid'] == $sessionid && $safecode == md5($row['id'] . $this->options['salt'] . md5($row['sessionid']))) {
                        $role = $this->get_role($row['role_id']);
                        if ($role) {
                            $this->id = $row['id'];
                            $this->username = $row['username'];
                            $this->nickname = $row['username'];
                            $this->role_id = $role['id'];
                            $this->fields = $row;
                            $this->rolefields = $role;
                            return TRUE;
                        }
                    }
                }
            }
        }
        return FALSE;
    }

    /**
     * 登录
     * @param string $username 用户名
     * @param string $password 密码
     * @param int $ttl 有效时长
     * @return boolean
     */
    public function login($username, $password, $ttl = 0) {
        $row = $this->db->one("SELECT * FROM {pre}admin WHERE username='{$username}'");
        if (is_array($row)) {
            //登录失败大于3次则开启验证码模式
            if ($row['loginfailure'] >= 3) {
                $captcha = strtoupper($_POST['captcha']);
                if ($captcha == '' || strlen($captcha) != 4) {
                    $this->error = '验证码不正确';
                    return FALSE;
                }
                $validcaptcha = $this->session->get("captcha");
                if ($captcha != $validcaptcha) {
                    $this->error = '验证码错误';
                    return FALSE;
                }
            }
            if ($row['password'] == md5(md5($password) . $row['salt'])) {
                $role = $this->get_role($row['role_id']);
                if ($role) {
                    $sessionid = Tools::getUniId();
                    $row['sessionid'] = $sessionid;
                    $this->cookie->set('id', $row['id'], $ttl);
                    $this->cookie->set('username', $row['username'], 86400 * 365);
                    $this->cookie->set('safecode', md5($row['id'] . $this->options['salt'] . md5($row['sessionid'])), $ttl);
                    $this->cookie->set('sessionid', $sessionid, $ttl);
                    $this->id = $row['id'];
                    $this->username = $row['username'];
                    $this->nickname = $row['username'];
                    $this->role_id = $role['id'];
                    $this->fields = $row;
                    $this->rolefields = $role;

                    $this->error = '';
                    $time = time();
                    $this->db->update("{pre}admin", array('logintime' => $time, 'sessionid' => $sessionid, 'loginfailure' => '0'), array('id' => $row['id']));
                    unset($row, $role);
                    return TRUE;
                } else {
                    $this->error = '权限信息错误';
                    return FALSE;
                }
            } else {
                $this->db->update("{pre}admin", array('loginfailure' => '#+1'), array('id' => $row['id']));
                $this->error = '密码不正确';
                return FALSE;
            }
        } else {
            $this->error = '用户名不正确';
            return FALSE;
        }
    }

    /**
     * 登出
     * @return boolean
     */
    public function logout() {
        $this->id = 0;
        $this->fields = array();
        $this->cookie->del('id');
        $this->cookie->del('sessionid');
        $this->cookie->del('safecode');
        $this->cookie->del('username');
        $this->cookie->del('sessionid');
        return TRUE;
    }

    /**
     * 判断是否有权限
     * @param string $controller
     * @param string $action
     * @return boolean
     */
    public function is_allow($controller = NULL, $action = NULL) {
        $controller = strtolower($controller);
        $action = strtolower($action);
        $controller = $controller ? $controller : 'index';
        $action = $action ? $action : 'index';
        if ($this->rolefields && isset($this->rolefields['permission'])) {
            if ($this->rolefields['id'] == 1)
                return TRUE;
            if (array_key_exists($controller, $this->rolefields['permission'])) {
                if ($action == "*") {
                    return TRUE;
                } else {
                    if (in_array($action, $this->rolefields['permission'][$controller])) {
                        return TRUE;
                    }
                }
            }
        }
        return FALSE;
    }

    /**
     * 获取指定角色的数据
     * @param int $role_id 角色ID
     * @return mixed
     */
    public function get_role($role_id) {
        $one = $this->db->one("SELECT * FROM {pre}role WHERE id = ? ", array($role_id));
        if ($one) {
            $one['permission'] = unserialize($one['permission']);
        }
        return $one;
    }

    /**
     * 修复子角色权限
     * @param array $childpermission 子角色权限树
     * @param array $fatherpermission 父角色权限树
     * @return array 子角色权限树
     */
    private function fixpermission($childpermission, $fatherpermission) {
        foreach ($childpermission as $k1 => $v1) {
            if (is_array($v1)) {
                if (array_key_exists($k1, $fatherpermission)) {
                    foreach ($v1 as $k2 => $v2) {
                        if (!in_array($v2, $fatherpermission[$k1])) {
                            unset($childpermission[$k1][$k2]);
                        }
                    }
                    $childpermission[$k1] = array_values($childpermission[$k1]);
                } else {
                    unset($childpermission[$k1]);
                }
            } else {
                unset($childpermission[$k1]);
            }
        }
        return $childpermission;
    }

}
